using UnityEngine;
using UnityEngine.EventSystems;
using System.Collections.Generic;
using System;

public class EventCenterSystem : TSingleton<EventCenterSystem>
{
    private class ValueList
    {

    }

    private static Dictionary<string, List<Action>> EventHandlerDic = new Dictionary<string, List<Action>>();
    private static Dictionary<string, List<Action>> AsyncEventHandlerDic = new Dictionary<string, List<Action>>();
    private static Dictionary<string, ValueList> AsyncEventParamsQueue = new Dictionary<string, ValueList>();

    protected override void OnDestroy()
    {
        EventHandlerDic.Clear();
        AsyncEventHandlerDic.Clear();
        base.OnDestroy();
    }

    private void LateUpdate()
    {
        if (AsyncEventParamsQueue.Count > 0)
        {
            foreach (var param in AsyncEventParamsQueue)
            {
                ExecuteAsyncHandler(param.Key);
            }
            AsyncEventParamsQueue.Clear();
        }
    }

    //--同步-----------------------------------------------------------------------------------------------

    public static void AddEventListener(string type, Action function)
    {
        List<Action> handler;
        if (!EventHandlerDic.TryGetValue(type, out handler))
        {
            handler = new List<Action>();
            EventHandlerDic[type] = handler;
        }
        handler.Add(function);
    }

    public static void RemoveEventLestener(string type, Action function)
    {
        List<Action> handler;
        if (EventHandlerDic.TryGetValue(type, out handler))
        {
            handler.Remove(function);
            if (handler.Count == 0)
                EventHandlerDic.Remove(type);
        }
    }

    private static void ExecuteHandler(string type)
    {
        List<Action> handler;
        if (EventHandlerDic.TryGetValue(type, out handler))
        {
            int i = 0;
            while (i < handler.Count)
            {
                if (handler[i] != null && handler[i].Method != null /*&& handler[i].Target != null*/)
                {
                    try
                    {
                        handler[i]();
                    }
                    catch (Exception e)
                    {
                        Debug.LogException(e);
                    }
                    i++;
                }
                else
                {
                    handler.RemoveAt(i);
                }
            }
            if (handler.Count == 0)
            {
                EventHandlerDic.Remove(type);
            }
        }
    }

    //--异步-----------------------------------------------------------------------------------------------

    /// <summary>
    /// 在LateUpdate中执行, 所有system更新以后，才会执行该事件。
    /// </summary>
    public static void AddAsyncEventLestener(string type, Action function)
    {
        List<Action> handler;
        if (!AsyncEventHandlerDic.TryGetValue(type, out handler))
        {
            handler = new List<Action>();
            AsyncEventHandlerDic[type] = handler;
        }
        handler.Add(function);
    }

    public static void RemoveAsyncEventLestener(string type, Action function)
    {
        List<Action> handler;
        if (AsyncEventHandlerDic.TryGetValue(type, out handler))
        {
            handler.Remove(function);
            if (handler.Count == 0)
                AsyncEventHandlerDic.Remove(type);
        }
    }

    private static void ExecuteAsyncHandler(string type)
    {
        List<Action> handler;
        if (AsyncEventHandlerDic.TryGetValue(type, out handler))
        {
            int i = 0;
            while (i < handler.Count)
            {
                if (handler[i] != null && handler[i].Method != null /*&& handler[i].Target != null*/)
                {
                    try
                    {
                        handler[i]();
                    }
                    catch (Exception e)
                    {
                        Debug.LogException(e);
                    }
                    i++;
                }
                else
                {
                    handler.RemoveAt(i);
                }
            }
            if (handler.Count == 0)
            {
                AsyncEventHandlerDic.Remove(type);
            }
        }
    }

    //--分发-----------------------------------------------------------------------------------------------

    public static void DespatchEvent(string type)
    {
        if (EventHandlerDic.ContainsKey(type))
        {
            ExecuteHandler(type);
        }
        if (AsyncEventHandlerDic.ContainsKey(type))
        {
            if (AsyncEventParamsQueue.ContainsKey(type))
            {
                AsyncEventParamsQueue[type] = new ValueList();
            }
            else
            {
                AsyncEventParamsQueue.Add(type, new ValueList());
            }
        }

        Debug.Log(string.Format("[DespatchEvent_{0}] : ", type));
    }
}

public class EventCenterSystem<T> : TSingleton<EventCenterSystem<T>>
{
    private class ValueList
    {
        public T Value1;

        public ValueList(T value1)
        {
            Value1 = value1;
        }
    }

    private static Dictionary<string, List<Action<T>>> EventHandlerDic = new Dictionary<string, List<Action<T>>>();
    private static Dictionary<string, List<Action<T>>> AsyncEventHandlerDic = new Dictionary<string, List<Action<T>>>();
    private static Dictionary<string, ValueList> AsyncEventParamsQueue = new Dictionary<string, ValueList>();

    protected override void OnDestroy()
    {
        EventHandlerDic.Clear();
        AsyncEventHandlerDic.Clear();
        base.OnDestroy();
    }

    private void LateUpdate()
    {
        if (AsyncEventParamsQueue.Count > 0)
        {
            foreach (var param in AsyncEventParamsQueue)
            {
                ExecuteAsyncHandler(param.Key, param.Value.Value1);
            }
            AsyncEventParamsQueue.Clear();
        }
    }

    //--同步-----------------------------------------------------------------------------------------------

    public static void AddEventListener(string type, Action<T> function)
    {
        List<Action<T>> handler;
        if (!EventHandlerDic.TryGetValue(type, out handler))
        {
            handler = new List<Action<T>>();
            EventHandlerDic[type] = handler;
        }
        handler.Add(function);
    }

    public static void RemoveEventLestener(string type, Action<T> function)
    {
        List<Action<T>> handler;
        if (EventHandlerDic.TryGetValue(type, out handler))
        {
            handler.Remove(function);
            if (handler.Count == 0)
                EventHandlerDic.Remove(type);
        }
    }

    private static void ExecuteHandler(string type, T param1)
    {
        List<Action<T>> handler;
        if (EventHandlerDic.TryGetValue(type, out handler))
        {
            int i = 0;
            while (i < handler.Count)
            {
                if (handler[i] != null && handler[i].Method != null /*&& handler[i].Target != null*/)
                {
                    try
                    {
                        handler[i](param1);
                    }
                    catch (Exception e)
                    {
                        Debug.LogException(e);
                    }
                    i++;
                }
                else
                {
                    handler.RemoveAt(i);
                }
            }
            if (handler.Count == 0)
            {
                EventHandlerDic.Remove(type);
            }
        }
    }

    //--异步-----------------------------------------------------------------------------------------------

    /// <summary>
    /// 在LateUpdate中执行, 所有system更新以后，才会执行该事件。
    /// </summary>
    public static void AddAsyncEventLestener(string type, Action<T> function)
    {
        List<Action<T>> handler;
        if (!AsyncEventHandlerDic.TryGetValue(type, out handler))
        {
            handler = new List<Action<T>>();
            AsyncEventHandlerDic[type] = handler;
        }
        handler.Add(function);
    }

    public static void RemoveAsyncEventLestener(string type, Action<T> function)
    {
        List<Action<T>> handler;
        if (AsyncEventHandlerDic.TryGetValue(type, out handler))
        {
            handler.Remove(function);
            if (handler.Count == 0)
                AsyncEventHandlerDic.Remove(type);
        }
    }

    private static void ExecuteAsyncHandler(string type, T param1)
    {
        List<Action<T>> handler;
        if (AsyncEventHandlerDic.TryGetValue(type, out handler))
        {
            int i = 0;
            while (i < handler.Count)
            {
                if (handler[i] != null && handler[i].Method != null /*&& handler[i].Target != null*/)
                {
                    try
                    {
                        handler[i](param1);
                    }
                    catch (Exception e)
                    {
                        Debug.LogException(e);
                    }
                    i++;
                }
                else
                {
                    handler.RemoveAt(i);
                }
            }
            if (handler.Count == 0)
            {
                AsyncEventHandlerDic.Remove(type);
            }
        }
    }

    //--分发-----------------------------------------------------------------------------------------------

    public static void DespatchEvent(string type, T param1)
    {
        if (EventHandlerDic.ContainsKey(type))
        {
            ExecuteHandler(type, param1);
        }
        if (AsyncEventHandlerDic.ContainsKey(type))
        {
            if (AsyncEventParamsQueue.ContainsKey(type))
            {
                AsyncEventParamsQueue[type] = new ValueList(param1);
            }
            else
            {
                AsyncEventParamsQueue.Add(type, new ValueList(param1));
            }
        }

        Debug.LogError(string.Format("[DespatchEvent_{0}] : \n--param1:{1}", type, param1));
    }
}

public class EventCenterSystem<T, U> : TSingleton<EventCenterSystem<T, U>>
{
    private class ValueList
    {
        public T Value1;
        public U Value2;

        public ValueList(T value1, U value2)
        {
            Value1 = value1;
            Value2 = value2;
        }
    }

    private static Dictionary<string, List<Action<T, U>>> EventHandlerDic = new Dictionary<string, List<Action<T, U>>>();
    private static Dictionary<string, List<Action<T, U>>> AsyncEventHandlerDic = new Dictionary<string, List<Action<T, U>>>();
    private static Dictionary<string, ValueList> AsyncEventParamsQueue = new Dictionary<string, ValueList>();

    protected override void OnDestroy()
    {
        EventHandlerDic.Clear();
        AsyncEventHandlerDic.Clear();
        base.OnDestroy();
    }

    private void LateUpdate()
    {
        if (AsyncEventParamsQueue.Count > 0)
        {
            foreach (var param in AsyncEventParamsQueue)
            {
                ExecuteAsyncHandler(param.Key, param.Value.Value1, param.Value.Value2);
            }
            AsyncEventParamsQueue.Clear();
        }
    }

    //--同步-----------------------------------------------------------------------------------------------

    public static void AddEventListener(string type, Action<T, U> function)
    {
        List<Action<T, U>> handler;
        if (!EventHandlerDic.TryGetValue(type, out handler))
        {
            handler = new List<Action<T, U>>();
            EventHandlerDic[type] = handler;
        }
        handler.Add(function);
    }

    public static void RemoveEventLestener(string type, Action<T, U> function)
    {
        List<Action<T, U>> handler;
        if (EventHandlerDic.TryGetValue(type, out handler))
        {
            handler.Remove(function);
            if (handler.Count == 0)
                EventHandlerDic.Remove(type);
        }
    }

    private static void ExecuteHandler(string type, T param1, U param2)
    {
        List<Action<T, U>> handler;
        if (EventHandlerDic.TryGetValue(type, out handler))
        {
            int i = 0;
            while (i < handler.Count)
            {
                if (handler[i] != null && handler[i].Method != null /*&& handler[i].Target != null*/)
                {
                    try
                    {
                        handler[i](param1, param2);
                    }
                    catch (Exception e)
                    {
                        Debug.LogException(e);
                    }
                    i++;
                }
                else
                {
                    handler.RemoveAt(i);
                }
            }
            if (handler.Count == 0)
            {
                EventHandlerDic.Remove(type);
            }
        }
    }

    //--异步-----------------------------------------------------------------------------------------------

    /// <summary>
    /// 在LateUpdate中执行, 所有system更新以后，才会执行该事件。
    /// </summary>
    public static void AddAsyncEventLestener(string type, Action<T, U> function)
    {
        List<Action<T, U>> handler;
        if (!AsyncEventHandlerDic.TryGetValue(type, out handler))
        {
            handler = new List<Action<T, U>>();
            AsyncEventHandlerDic[type] = handler;
        }
        handler.Add(function);
    }

    public static void RemoveAsyncEventLestener(string type, Action<T, U> function)
    {
        List<Action<T, U>> handler;
        if (AsyncEventHandlerDic.TryGetValue(type, out handler))
        {
            handler.Remove(function);
            if (handler.Count == 0)
                AsyncEventHandlerDic.Remove(type);
        }
    }

    private static void ExecuteAsyncHandler(string type, T param1, U param2)
    {
        List<Action<T, U>> handler;
        if (AsyncEventHandlerDic.TryGetValue(type, out handler))
        {
            int i = 0;
            while (i < handler.Count)
            {
                if (handler[i] != null && handler[i].Method != null /*&& handler[i].Target != null*/)
                {
                    try
                    {
                        handler[i](param1, param2);
                    }
                    catch (Exception e)
                    {
                        Debug.LogException(e);
                    }
                    i++;
                }
                else
                {
                    handler.RemoveAt(i);
                }
            }
            if (handler.Count == 0)
            {
                AsyncEventHandlerDic.Remove(type);
            }
        }
    }

    //--分发-----------------------------------------------------------------------------------------------

    public static void DespatchEvent(string type, T param1, U param2)
    {
        if (EventHandlerDic.ContainsKey(type))
        {
            ExecuteHandler(type, param1, param2);
        }
        if (AsyncEventHandlerDic.ContainsKey(type))
        {
            if (AsyncEventParamsQueue.ContainsKey(type))
            {
                AsyncEventParamsQueue[type] = new ValueList(param1, param2);
            }
            else
            {
                AsyncEventParamsQueue.Add(type, new ValueList(param1, param2));
            }
        }

        Debug.Log(string.Format("[DespatchEvent_{0}] : \n" + "--param1:{1}  --param2:{2}", type, param1, param2));
    }
}

public class EventCenterSystem<T, U, I> : TSingleton<EventCenterSystem<T, U, I>>
{
    private class ValueList
    {
        public T Value1;
        public U Value2;
        public I Value3;

        public ValueList(T value1, U value2, I value3)
        {
            Value1 = value1;
            Value2 = value2;
            Value3 = value3;
        }
    }

    private static Dictionary<string, List<Action<T, U, I>>> EventHandlerDic = new Dictionary<string, List<Action<T, U, I>>>();
    private static Dictionary<string, List<Action<T, U, I>>> AsyncEventHandlerDic = new Dictionary<string, List<Action<T, U, I>>>();
    private static Dictionary<string, ValueList> AsyncEventParamsQueue = new Dictionary<string, ValueList>();

    protected override void OnDestroy()
    {
        EventHandlerDic.Clear();
        AsyncEventHandlerDic.Clear();
        base.OnDestroy();
    }

    private void LateUpdate()
    {
        if (AsyncEventParamsQueue.Count > 0)
        {
            foreach (var param in AsyncEventParamsQueue)
            {
                ExecuteAsyncHandler(param.Key, param.Value.Value1, param.Value.Value2, param.Value.Value3);
            }
            AsyncEventParamsQueue.Clear();
        }
    }

    //--同步-----------------------------------------------------------------------------------------------

    public static void AddEventListener(string type, Action<T, U, I> function)
    {
        List<Action<T, U, I>> handler;
        if (!EventHandlerDic.TryGetValue(type, out handler))
        {
            handler = new List<Action<T, U, I>>();
            EventHandlerDic[type] = handler;
        }
        handler.Add(function);
    }

    public static void RemoveEventLestener(string type, Action<T, U, I> function)
    {
        List<Action<T, U, I>> handler;
        if (EventHandlerDic.TryGetValue(type, out handler))
        {
            handler.Remove(function);
            if (handler.Count == 0)
                EventHandlerDic.Remove(type);
        }
    }

    private static void ExecuteHandler(string type, T param1, U param2, I param3)
    {
        List<Action<T, U, I>> handler;
        if (EventHandlerDic.TryGetValue(type, out handler))
        {
            int i = 0;
            while (i < handler.Count)
            {
                if (handler[i] != null && handler[i].Method != null /*&& handler[i].Target != null*/)
                {
                    try
                    {
                        handler[i](param1, param2, param3);
                    }
                    catch (Exception e)
                    {
                        Debug.LogException(e);
                    }
                    i++;
                }
                else
                {
                    handler.RemoveAt(i);
                }
            }
            if (handler.Count == 0)
            {
                EventHandlerDic.Remove(type);
            }
        }
    }

    //--异步-----------------------------------------------------------------------------------------------

    /// <summary>
    /// 在LateUpdate中执行, 所有system更新以后，才会执行该事件。
    /// </summary>
    public static void AddAsyncEventLestener(string type, Action<T, U, I> function)
    {
        List<Action<T, U, I>> handler;
        if (!AsyncEventHandlerDic.TryGetValue(type, out handler))
        {
            handler = new List<Action<T, U, I>>();
            AsyncEventHandlerDic[type] = handler;
        }
        handler.Add(function);
    }

    public static void RemoveAsyncEventLestener(string type, Action<T, U, I> function)
    {
        List<Action<T, U, I>> handler;
        if (AsyncEventHandlerDic.TryGetValue(type, out handler))
        {
            handler.Remove(function);
            if (handler.Count == 0)
                AsyncEventHandlerDic.Remove(type);
        }
    }

    private static void ExecuteAsyncHandler(string type, T param1, U param2, I param3)
    {
        List<Action<T, U, I>> handler;
        if (AsyncEventHandlerDic.TryGetValue(type, out handler))
        {
            int i = 0;
            while (i < handler.Count)
            {
                if (handler[i] != null && handler[i].Method != null /*&& handler[i].Target != null*/)
                {
                    try
                    {
                        handler[i](param1, param2, param3);
                    }
                    catch (Exception e)
                    {
                        Debug.LogException(e);
                    }
                    i++;
                }
                else
                {
                    handler.RemoveAt(i);
                }
            }
            if (handler.Count == 0)
            {
                AsyncEventHandlerDic.Remove(type);
            }
        }
    }

    //--分发-----------------------------------------------------------------------------------------------

    public static void DespatchEvent(string type, T param1, U param2, I param3)
    {
        if (EventHandlerDic.ContainsKey(type))
        {
            ExecuteHandler(type, param1, param2, param3);
        }
        if (AsyncEventHandlerDic.ContainsKey(type))
        {
            if (AsyncEventParamsQueue.ContainsKey(type))
            {
                AsyncEventParamsQueue[type] = new ValueList(param1, param2, param3);
            }
            else
            {
                AsyncEventParamsQueue.Add(type, new ValueList(param1, param2, param3));
            }
        }

        Debug.LogError(string.Format("[DespatchEvent_{0}] : \n" + "--param1:{1}  --param2:{2}  --param3:{3}", type, param1, param2, param3));
    }
}

public class EventCenterSystem<T, U, I, O> : TSingleton<EventCenterSystem<T, U, I, O>>
{
    private class ValueList
    {
        public T Value1;
        public U Value2;
        public I Value3;
        public O Value4;

        public ValueList(T value1, U value2, I value3, O value4)
        {
            Value1 = value1;
            Value2 = value2;
            Value3 = value3;
            Value4 = value4;
        }
    }

    private static Dictionary<string, List<Action<T, U, I, O>>> EventHandlerDic = new Dictionary<string, List<Action<T, U, I, O>>>();
    private static Dictionary<string, List<Action<T, U, I, O>>> AsyncEventHandlerDic = new Dictionary<string, List<Action<T, U, I, O>>>();
    private static Dictionary<string, ValueList> AsyncEventParamsQueue = new Dictionary<string, ValueList>();

    protected override void OnDestroy()
    {
        EventHandlerDic.Clear();
        AsyncEventHandlerDic.Clear();
        base.OnDestroy();
    }

    private void LateUpdate()
    {
        if (AsyncEventParamsQueue.Count > 0)
        {
            foreach (var param in AsyncEventParamsQueue)
            {
                ExecuteAsyncHandler(param.Key, param.Value.Value1, param.Value.Value2, param.Value.Value3, param.Value.Value4);
            }
            AsyncEventParamsQueue.Clear();
        }
    }

    //--同步-----------------------------------------------------------------------------------------------

    public static void AddEventListener(string type, Action<T, U, I, O> function)
    {
        List<Action<T, U, I, O>> handler;
        if (!EventHandlerDic.TryGetValue(type, out handler))
        {
            handler = new List<Action<T, U, I, O>>();
            EventHandlerDic[type] = handler;
        }
        handler.Add(function);
    }

    public static void RemoveEventLestener(string type, Action<T, U, I, O> function)
    {
        List<Action<T, U, I, O>> handler;
        if (EventHandlerDic.TryGetValue(type, out handler))
        {
            handler.Remove(function);
            if (handler.Count == 0)
                EventHandlerDic.Remove(type);
        }
    }

    private static void ExecuteHandler(string type, T param1, U param2, I param3, O param4)
    {
        List<Action<T, U, I, O>> handler;
        if (EventHandlerDic.TryGetValue(type, out handler))
        {
            int i = 0;
            while (i < handler.Count)
            {
                if (handler[i] != null && handler[i].Method != null /*&& handler[i].Target != null*/)
                {
                    try
                    {
                        handler[i](param1, param2, param3, param4);
                    }
                    catch (Exception e)
                    {
                        Debug.LogException(e);
                    }
                    i++;
                }
                else
                {
                    handler.RemoveAt(i);
                }
            }
            if (handler.Count == 0)
            {
                EventHandlerDic.Remove(type);
            }
        }
    }

    //--异步-----------------------------------------------------------------------------------------------

    /// <summary>
    /// 在LateUpdate中执行, 所有system更新以后，才会执行该事件。
    /// </summary>
    public static void AddAsyncEventLestener(string type, Action<T, U, I, O> function)
    {
        List<Action<T, U, I, O>> handler;
        if (!AsyncEventHandlerDic.TryGetValue(type, out handler))
        {
            handler = new List<Action<T, U, I, O>>();
            AsyncEventHandlerDic[type] = handler;
        }
        handler.Add(function);
    }

    public static void RemoveAsyncEventLestener(string type, Action<T, U, I, O> function)
    {
        List<Action<T, U, I, O>> handler;
        if (AsyncEventHandlerDic.TryGetValue(type, out handler))
        {
            handler.Remove(function);
            if (handler.Count == 0)
                AsyncEventHandlerDic.Remove(type);
        }
    }

    private static void ExecuteAsyncHandler(string type, T param1, U param2, I param3, O param4)
    {
        List<Action<T, U, I, O>> handler;
        if (AsyncEventHandlerDic.TryGetValue(type, out handler))
        {
            int i = 0;
            while (i < handler.Count)
            {
                if (handler[i] != null && handler[i].Method != null /*&& handler[i].Target != null*/)
                {
                    try
                    {
                        handler[i](param1, param2, param3, param4);
                    }
                    catch (Exception e)
                    {
                        Debug.LogException(e);
                    }
                    i++;
                }
                else
                {
                    handler.RemoveAt(i);
                }
            }
            if (handler.Count == 0)
            {
                AsyncEventHandlerDic.Remove(type);
            }
        }
    }

    //--分发-----------------------------------------------------------------------------------------------

    public static void DespatchEvent(string type, T param1, U param2, I param3, O param4)
    {
        if (EventHandlerDic.ContainsKey(type))
        {
            ExecuteHandler(type, param1, param2, param3, param4);
        }
        if (AsyncEventHandlerDic.ContainsKey(type))
        {
            if (AsyncEventParamsQueue.ContainsKey(type))
            {
                AsyncEventParamsQueue[type] = new ValueList(param1, param2, param3, param4);
            }
            else
            {
                AsyncEventParamsQueue.Add(type, new ValueList(param1, param2, param3, param4));
            }
        }

        Debug.Log(string.Format("[DespatchEvent_{0}] : \n" + "--param1:{1}  --param2:{2}  --param3:{3}  --param4:{4}", type, param1, param2, param3, param4));
    }
}

